本文初始编辑地址,源自我的CSDN博客:我的CSDN博客

这篇博客同步更新于我的GitHub博客:我的GitHub博客

面试回顾:腾讯面试回顾

1.js中ajax发送请求的步骤

在js中,有一个用于异步请求的对象,XMLHttpRquest对象,使用该对象可以向服务端发送请求(post,get,put...)。原生的方法步骤如下:

①创建XMLHttpRequest对象(标准浏览器):

1
2
3
if(window.XMLHttpRequest){
var xhr = new XMLHttpRequest();
}

IE7及以下,这个对象为:ActiveXObject:

1
2
3
if(window.ActiveXObject){
var xhr = new ActiveXObject('Microsoft.XMLHTTP')
}

② 初始化请求

1
xhr.open('GET','http://www.请求地址.com',是否异步?true:false);

③发送请求/传递数据

1
xhr.send();

请求的文件路径,如果是GET方式,直接缀在请求地址的后面,以如下的形式:

1
2
//数据
xhr.open('GET','http://www.请求地址.com/index.html',true);

如果是POST方法,直接写 xhr.send('数据') 中。

④设置异步回调callback()
先给个错误示范:

1
2
3
4
5
//xhr.readyState 本地的请求状态
//xhr.status 服务器返回的请求状态码
if(xhr.readystate==4 && xhr.status == 200){
do something...
}

这里的本质原因是没有本地xhr对象改变的事件,因此这里的readystate会一直长等于 1

这里的异步方式主要通过一个事件来完成:

1
2
3
4
5
6
7
xhr.onreadystatechange()=function(){

if(xhr.readystate==4 && xhr.status == 200){
do something...
}

}

如果在步骤②中请求的方式是同步的,一旦服务器压力过大,没有及时响应,那么代码会一直卡在这里,一直傻傻的等到服务器响应200,才会do something。

反之,如果请求方式是异步的,那么这里的响应无论是否及时,都不会阻塞后面的代码。

扩展:既然 readyState==4 && status ==200 是一个回调,那么我们也可以使用其他的http状态码来设置不同的回调~
参考文章 ,我以前的博客:Ajax初探
上一次的面试中,xhr.open()初始化 xhr.send()发送请求 xhr.onreadystatechange=function(){}回调函数 这三点都忘记答了,一定要注意。

2.浏览器里面的事件都会按照一定的规则去传递,这个规则是什么?

事件捕获、事件响应、事件冒泡。

如图:

事件捕获和冒泡

事件捕获和冒泡

不管body上绑定事件、或者div甚至div的text节点上绑定事件,这个事件必须先从根节点开始遍历(即Window对象开始),从上往下,传递的过程中,发现有的元素绑定了事件,也先放着,等全部事件捕获完毕(遍历完毕), 开始处理事件,处理的顺序为,从最小的根节点上的事件开始,依次向上冒泡。

一句话概括这种机制:

捕获:自外而内,从根到叶,从大到小 。

冒泡:自内而外,从叶到根,从小到大。

来做个实验,有如下的html结构 和 js代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!--HTML结构-->
<div id="div1">
我是DIV1
<div id="div2">
我是DIV2
<button id="btn">
i am a button
</button>
</div>
</div>


//script代码

var div1 = document.getElementById('div1');
var div2 = document.getElementById('div2');
var btn = document.getElementById('btn');

btn.addEventListener('click', function() {console.log(this.id)},false);


div2.addEventListener('click', function(){console.log(this.id)},false);

div1.addEventListener('click', function(){console.log(this.id)},false);

HTML结构如图:

HTML结构

HTML结构

当点击最里面的button,会依次出现这种情况:

控制台输出

控制台输出

可以看到,事件是在冒泡阶段被触发的。

当改变js API中最后一个Boolean值为true时,又会产生另外一种景观:

这里写图片描述

这里写图片描述

这次是从外向内依次触发的。

总结:
1.addEventListener(事件,函数,boolean?捕获:冒泡),这个API可以设置事件触发于捕获/冒泡阶段,而且这个事件可以复写。
2.普通的API,例如 onclick ,onmouse 默认只能在冒泡阶段触发,而且不能复写,复写事件会覆盖。

3.闭包是怎么回事?用在什么场景?

简而言之:1、闭包就是可以访问局部作用域的变量。
并且: 2、 可以使局部变量常驻内存
参考阮一峰老师的闭包博客: 阮一峰—-闭包

Q:闭包的内部函数为什么变量不会被销毁?
A:

1
2
3
4
5
6
7
8
9
10
function a(){
var a =1;

function b(){
a+=1;
return a;
}
return b();

}

因为此时的子函数b一直对于a函数的变量“a=1”有需求,因此这个变量会常驻内存,不会被销毁。

Q 3.1:什么时候才能够销毁这个内存呢?(销毁机制和人为销毁方法)

A:浏览器中的js引擎有自己的垃圾回收机制,当一个变量或者对象引用为0的时候,会自动回收。
人为的销毁内存的办法:1.关闭网页,结束js运行环境。2.销毁变量,为变量赋值 null;

Q3.2:如何避免内存泄漏的问题?
A:减少全局空间的污染,良好的变量定义习惯。减少变量的引用。

4.CALL和Apply是干嘛的?

二者都是为了更改function 的this指针,举个例子

CALL(新的this对象,原先的参数1,原先的参数2…);
Apply(新的this对象,[原先的参数1,原先的参数2…]);

先传入新的this对象,再传入旧方法的传参。

5.在平时开发中,遇到过跨域的问题吗?如何处理跨域呢?

1.jsonp跨域
利用<script>标签的跨域特性,将请求的语句写在script标签的src属性上,然后定义一个方法,用于接受返回值responseText。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//在js预先定义好callback()函数  

function fun(data){

//use data to do somethings.

}


//动态创建script标签,并在url中说明请求地址
var body = document.getElementsByTagName('body')[0];

var script = document.createElement('script');

script.type = 'text/javasctipt';

script.src = 'require.php?callback=fun';

body.appendChild(script);

//Script插入完成,一旦服务端有响应,传递过来的响应文本会直接被当做js代码执行。
//假设传回的值是 fun({"name":"xiaoming"}),那么小明这个对象会被当做参数传递给早就定义好的fun()函数。

这样,通过script不受跨域访问的特性,实现了跨域访问。

2.CORS跨域(主流浏览器及IE10+)
对于客户端,我们还是正常使用xhr对象发送ajax请求。
唯一需要注意的是,我们需要设置我们的xhr属性withCredentials为true,不然的话,cookie是带不过去的哦,设置: xhr.withCredentials = true;
对于服务器端,需要在 response header中设置如下两个字段:
Access-Control-Allow-Origin: http://www.yourhost.com
Access-Control-Allow-Credentials:true
这样,我们就可以跨域请求接口了。

3.返回的json和jsonp有什么区别?
返回的json是json格式的文件,而返回的jsonp是字符串形式的文件,形如:

1
callback({"name":"HanMeiMei"})

觉得文章有用?点击下方打赏,鼓励作者更好的写作!